// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2012-2019.
 * Description: support nand flash driver
 * Author: caizhiyong <caizhiyong@hisilicon.com>
 * Create: 2018-10-26
 */

#ifndef HISFC300H
#define HISFC300H
#include <asm/setup.h>
#include <mach/kexport.h>

#define CONFIG_HISFC300_PERIPHERY_REGBASE 0x0
#ifndef CONFIG_HISFC300_REG_BASE_ADDRESS
#define CONFIG_HISFC300_REG_BASE_ADDRESS            (0x10a20000)
#endif

#ifndef CONFIG_HISFC300_BUFFER_BASE_ADDRESS
#define CONFIG_HISFC300_BUFFER_BASE_ADDRESS         (0x1C000000)
#endif

#ifndef CONFIG_HISFC300_CHIP_NUM
#define CONFIG_HISFC300_CHIP_NUM                    (2)
#endif

#define CONFIG_SPI_FLASH_BIG 1

#define ioremap_nocache(phy, sz)        ioremap(phy, sz)
#define HISFC300_REG_BASE_LEN                  (0x100)
#define HISFC300_PERIPHERY_REG_LEN             (0x100)

#define HISFC300_BUFFER_BASE_LEN               (0x4000000) /* 64MB */
#define HISFC300_MAX_READY_WAIT_JIFFIES        (40 * HZ)

#define HISFC200_MEM_READ_SLICE                (512)

#define HISFC300_PARTITION_HEAD_LEN            (2)
#define HISFC300_TAG_TABLE_MAGIC               (0x48695370)
#define HISFC300_READ_CHIPID_MAGIC             (0x118417)

/*CMD_CONFIG*/
#define HISFC300_CMD_CS(_cs)                (((_cs) & 0x01) << 1)
#define HISFC300_CMD_START                  (1 << 0)
#define HISFC300_CMD_ADDR_EN                (1 << 3)
#define HISFC300_CMD_DUMMY_CNT(_n)          (((_n) & 0x07) << 4)
#define HISFC300_CMD_DATA_EN                (1 << 7)
#define HISFC300_CMD_DATA_RW                (1 << 8)
#define HISFC300_CMD_DATA_CNT(_n)           ((((_n) - 1) & 0xFF) << 9)
#define HISFC300_CMD_IF_TYPE(_n)            (((_n) & 0x07) << 17)

/*GLOBAL_CONFIG*/
#define HISFC300_CONFIG_MODE3               (1 << 0)
#define HISFC300_CONFIG_WP_EN               (1 << 1)
#define HISFC300_CONFIG_ADDR_MODE           (1 << 1)
#define HISFC300_CONFIG_RD_DELAY(_n)        (((_n) & 0x03) << 3)

#define HISFC300_ADDR_MASK                  (0x3FFFFFFF)


#define   HISFC300_GLOBAL_CONFIG          0x100
#define   HISFC300_TIMING2                0x110
#define   HISFC300_INT_RAW_STATUS         0x120
#define   HISFC300_INT_STATUS             0x124
#define   HISFC300_INT_MASK               0x128
#define   HISFC300_INT_CLEAR              0x12C
#define   HISFC300_VERSION                0x1F8
#define   HISFC300_VERSION_SEL            0x1FC
#define   HISFC300_BUS_CONFIG1            0x200
#define   HISFC300_BUS_CONFIG2            0x204
#define   HISFC300_BUS_FLASH_SIZE         0x210
#define   HISFC300_BUS_BASE_ADDR_CS0      0x214
#define   HISFC300_BUS_BASE_ADDR_CS1      0x218
#define   HISFC300_BUS_ALIAS_ADDR         0x21C
#define   HISFC300_BUS_ALIAS_CS           0x220
#define   HISFC300_CMD_CONFIG             0x300
#define   HISFC300_INS                    0x308
#define   HISFC300_ADDR                   0x30C
#define   HISFC300_DATABUF1               0x400
#define   HISFC300_DATABUF2               0x404
#define   HISFC300_DATABUF64              0x4FC

#define   HISFC300_TIMING_TSHSL(_n)            ((_n) & 0xF)
#define   HISFC300_TIMING_TCSS(_n)             (((_n) & 0x7) << 8)
#define   HISFC300_TIMING_TCSH(_n)             (((_n) & 0x7) << 12)

#define   HISFC300_CHECK_STATUS_LOOP_MAX       10000000

struct hisfc_spi {
	char *name;
	unsigned int chipselect;
	unsigned long long chipsize;
	unsigned int erasesize;
	void __iomem *iobase;
	unsigned int addrcycle;
	struct spi_operation read[1];
	struct spi_operation write[1];
	struct spi_operation erase[MAX_SPI_OP];
	/*
	 * BP mask has 8 bits,when BP occupy 3 bits,BP_bitmask is 0x07 (0000 0111), or 4 bits,
	 * the value is 0x0f (0000 1111);default value is 0x07
	 */
	unsigned char BP_bitmask;
};

struct hisfc_host {
	struct mtd_info mtd[1];
	void __iomem *iobase;
	void __iomem *regbase;
	struct device *dev;
	struct mutex lock;
	void __iomem *cfgreg;

	int add_partition;
	int num_chip;
	struct hisfc_spi spi[CONFIG_HISFC300_CHIP_NUM+1];

	int (*suspend)(struct platform_device *pltdev, pm_message_t state);
	int (*resume)(struct platform_device *pltdev);
};

#define MTD_TO_HOST(_mtd)               ((struct hisfc_host *)(_mtd))

int hi_sfc_type_get(void);

#define hisfc_read(_host, _reg) \
	((unsigned int)readl((char *)_host->regbase + (_reg)))

#define hisfc_write(_host, _reg, _value) \
	writel((_value), (char *)_host->regbase + (_reg))

#define DBG_MSG(_fmt, arg...)
#define DBG_WARN(_fmt, arg...)
#define DBG_BUG(fmt, args...) do { \
	pr_err("[%s:%d] BUG !!! " fmt, __func__, __LINE__, ##args); \
	while (1) \
		; \
} while (0)

#ifndef COMMAND_LINE_SIZE
/* 2048 is enough for both aarch64 and arm32
 * on arm32, the command line will be truncated to 1024 by linux automatically */
#define COMMAND_LINE_SIZE 2048
#endif

extern char g_flash_cmd_line[];
extern char __initdata save_cmd_line[COMMAND_LINE_SIZE];
int local_del_mtd_partitions(struct mtd_info *mtd);
int local_del_mtd_device(struct mtd_info *mtd);
extern int local_add_mtd_device(struct mtd_info *mtd);
extern int local_parse_mtd_partitions(struct mtd_info *master, const char * const *types,
	struct mtd_part_parser_data *data);
#endif
